/**
 * @author: Abandon <17386012013@163.com>
 * Date: 2024-07-31
 * Last Modified Date: 2024-07-31
 * Last Modified By: Abandon <17386012013@163.com>
 */
import { DomEditor, IDomEditor, SlateEditor, SlateTransforms } from '@wangeditor/editor';
import { hasUndeletableNode, hasDavinciBlockNode } from './helper';

export function withDavinci<T extends IDomEditor>(editor: T): T {
	const { isInline, isVoid, deleteBackward, deleteForward, addMark, deleteFragment, normalizeNode } = editor;
	const newEditor = editor;

	setTimeout(() => {
		console.log('plugin Davinci');

		const { $textArea } = DomEditor.getTextarea(newEditor);
		if ($textArea == null) return;
		let startSelect = false;

		console.log('$textArea', $textArea);

		// $textArea[0].dom7Listeners = null;
		// 重新渲染数据 修复中文输入 davinci-block
		// console.log(getEventListeners($textArea));

		$textArea.on('mousemove', e => {
			e.preventDefault();
			if (newEditor.selection && hasUndeletableNode(newEditor)) {
				newEditor.deselect();
			}
		});
		$textArea.on('compositionstart', e => {
			e.preventDefault();
			if (hasDavinciBlockNode(newEditor)) {
				newEditor.move(1);
			}
		});
		$textArea.on('keydown', e => {
			if (e.shiftKey) {
				e.preventDefault();
				newEditor.deselect();
			}
		};

		// 防止不可删元素被选中
		$textArea.on('mousedown', e => {
			startSelect = true;
		});
		// 防止不可删的元素被选中
		document.addEventListener('mousemove', e => {
			if (!startSelect) return;
			deselectUndeletableNode(e);
		});
		document.addEventListener('mouseup', e => {
			deselectUndeletableNode(e);
			startSelect = false;
		});
		$textArea.on('compositionstart', e => {
			if (editor.selection && hasUndeletableNode(newEditor)) {
				e.preventDefault();
				newEditor.move(1);
			}
		});
		$textArea.on('compositionupdate', e => {
			deselectUndeletableNode(e);
		});

		$textArea.on('beforeinput', e => {
			e.preventDefault();
			if (hasDavinciBlockNode(newEditor)) {
				newEditor.move(1);
			}
		});
		$textArea.on('keydown', e => {
			if (e.shiftKey) {
				deselectUndeletableNode(e);
			}
			if (e.ctrlKey && e.keyCode == 65) {
				deselectUndeletableNode(e);
			}
		});
	});

	// newEditor.undo = () => {};
	// 重写addMark
	newEditor.addMark = (key, value) => {
		const nodeEntries = SlateEditor.nodes(newEditor, {
			match: node => node,
			universal: true,
			mode: 'lowest'
		});
		try {
			if (nodeEntries) {
				for (let nodeEntry of [...nodeEntries]) {
					const [node, path] = nodeEntry;
					const isLegalKey = ['fontSize'].includes(key);
					if (node?.type === 'davinci-block' && isLegalKey) {
						const props = {};
						props[key] = value;
						SlateTransforms.setNodes(newEditor, props, {
							at: path
						});
					}
				}
			}
		} catch (error) {}
		addMark(key, value);
	};
	// 重写 isInline
	newEditor.isInline = elem => {
		const type = DomEditor.getNodeType(elem);
		if (type === 'davinci-block') {
			return true;
		}
		return isInline(elem);
	};

	// 重写 isVoid
	newEditor.isVoid = elem => {
		const type = DomEditor.getNodeType(elem);
		if (type === 'davinci-block') {
			return true;
		}
		return isVoid(elem);
	};

	//重写删除
	newEditor.deleteBackward = unit => {
		console.log('deleteBackward');
		let prev = SlateEditor.previous(editor);
		// @ts-ignore
		if (prev?.length && prev[0]?.type?.startsWith?.('davinci') && prev[0]?.undeletable) return;
		deleteBackward(unit);
	};

	//重写删除
	newEditor.deleteForward = unit => {
		console.log('deleteForward');
		let next = SlateEditor.next(editor);
		// @ts-ignore
		if (next?.length && next[0]?.type?.startsWith?.('davinci') && next[0]?.undeletable) return;
		deleteForward(unit);
	};

	newEditor.deleteFragment = direction => {
		console.log('deleteFragment');
		if (hasUndeletableNode(newEditor)) return;
		deleteFragment(direction);
	};

	newEditor.normalizeNode = ([node, path]) => {
		const type = DomEditor.getNodeType(node);
		if (type === 'davinci-block') {
			const isLast = DomEditor.isLastNode(newEditor, node);
			if (isLast) {
				SlateTransforms.insertNodes(newEditor, DomEditor.genEmptyParagraph(), { at: [path[0] + 1] });
			}
		}
		// 执行默认的 normalizeNode ，重要！！！
		return normalizeNode([node, path]);
	};
	return newEditor;
}
